﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OthelloGame;
using System.Collections;
using System.Threading;

namespace OthelloCognition
{
    public class NaiveSolver : AbstractSolver
    {
        GreedySolver greeedy = new GreedySolver(Heuristics.Score);

        Queue<OthelloGameBoard> boardsToExpand = new Queue<OthelloGameBoard>();
        Hashtable expandedBoardsWithStartingMove = new Hashtable();

        int countAtBestPlace = 0;
        PieceColors maxPlayer;

        private void clearStart()
        {
            expandedBoardsWithStartingMove.Clear();
            boardsToExpand.Clear();
            countAtBestPlace = 0;
        }

        public override int expanded
        {
            get { return count + greeedy.expanded; }
        }

        public override SolverEnum SolverName()
        {
            return SolverEnum.Naive;
        }

        protected override void examineBoard(OthelloGameBoard board)
        {
            clearStart();
            maxPlayer = board.PlayersTurn;
            OthelloGameBoard next = board;
            do
            {
                next = examineLevel(next);
            } while (next != null);
        }

        private OthelloGameBoard examineLevel(OthelloGameBoard current)
        {
            OthelloGameBoard nextExpansion = null;
            if (current.PlayersTurn == maxPlayer) //explore all possabilities for brains choice.
            {
                OthelloGameBoard nextBoard;

                foreach (OthelloBoardLocation pit in current.AvailableOptionLocations)
                {
                    nextBoard = expandState(current, pit);

                    //Add Board to rememberd "graph" nodes.
                    //remember all previously expanded nodes.
                    if (!expandedBoardsWithStartingMove.Contains(current))
                    {
                        if (!expandedBoardsWithStartingMove.Contains(nextBoard))
                        {
                            //fringe
                            boardsToExpand.Enqueue(nextBoard);
                            expandedBoardsWithStartingMove.Add(nextBoard, pit);
                        }
                    }
                    else if (!expandedBoardsWithStartingMove.ContainsKey(nextBoard))
                    {
                        //fringe
                        boardsToExpand.Enqueue(nextBoard);
                        Console.WriteLine("Size of table: " + expandedBoardsWithStartingMove.Count);
                        //if its not the first level of this BFS then record the initial move that lead to this new board.
                        expandedBoardsWithStartingMove[nextBoard] = expandedBoardsWithStartingMove[current];
                    }


                    //Record if Optimal solution.
                    int newPitCount = nextBoard.PitCount(maxPlayer);
                    if (newPitCount > countAtBestPlace)
                    {
                        countAtBestPlace = newPitCount;
                        move = (OthelloBoardLocation)expandedBoardsWithStartingMove[nextBoard];
                    }
                }

                if (boardsToExpand.Count() > 0)
                {
                    nextExpansion = boardsToExpand.Dequeue();// recursivelyExamineBoard(boardsToExpand.Dequeue());
                }

            }
            else //simulate Players Greedy choice for them.
            {
                greeedy.searchGameState(current);

                OthelloGameBoard best = expandState(current, greeedy.nextMove);

                //If two of the brains moves have the same next best possible move then
                //ignore it, and move on to the next of the brains branches.
                if (!expandedBoardsWithStartingMove.Contains(best))
                {
                    expandedBoardsWithStartingMove.Add(best, (OthelloBoardLocation)expandedBoardsWithStartingMove[current]);
                    nextExpansion = best; // recursivelyExamineBoard(best);
                }
                else if (boardsToExpand.Count() > 0)
                {
                    nextExpansion = boardsToExpand.Dequeue();
                }

            }

            return nextExpansion;
        }


    }
}
